package me.sdevil507.org.service.impl;

import com.google.common.collect.Lists;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import me.sdevil507.biz.common.exceptions.DeptCodeExistedException;
import me.sdevil507.biz.common.exceptions.DeptTitleExistedException;
import me.sdevil507.org.dto.OrgDeptParamsDto;
import me.sdevil507.org.mapper.OrgDeptMapper;
import me.sdevil507.org.po.OrgDeptPo;
import me.sdevil507.org.po.OrgPo;
import me.sdevil507.org.po.OrgUserPo;
import me.sdevil507.org.po.QOrgDeptPo;
import me.sdevil507.org.repository.OrgDeptRepository;
import me.sdevil507.org.repository.OrgRepository;
import me.sdevil507.org.repository.OrgUserRepository;
import me.sdevil507.org.service.OrgDeptService;
import me.sdevil507.platform.po.PlatDeptPo;
import me.sdevil507.platform.po.QPlatDeptPo;
import me.sdevil507.supports.jpa.PageParamsDTO;
import me.sdevil507.supports.jpa.SortParamsDTO;
import me.sdevil507.supports.shiro.helper.OrgAccountHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;

/**
 * 机构部门表[OrgDeptServiceImpl]
 *
 * @author sdevil507
 * created on 2020-06-24 14:31:02
 */
@Service
public class OrgDeptServiceImpl implements OrgDeptService {

    @Resource
    private OrgDeptRepository orgDeptRepository;

    @Resource
    private OrgRepository orgRepository;

    @Resource
    private OrgUserRepository orgUserRepository;

    @Autowired
    private OrgDeptMapper orgDeptMapper;

    @Override
    public List<OrgDeptPo> readAll(OrgDeptParamsDto searchParamsDto) {
        QOrgDeptPo qOrgDeptPo = QOrgDeptPo.orgDeptPo;

        // 开启谓语查询条件
        Predicate predicate = qOrgDeptPo.id.isNotNull().and(qOrgDeptPo.deleted.eq(false));
        if(OrgAccountHelper.getOrgId() != null) {
            predicate = ExpressionUtils.and(predicate, qOrgDeptPo.id.eq(OrgAccountHelper.getOrgId()));
//            predicate = ExpressionUtils.and(predicate, qOrgDeptPo.itIsOrg.isTrue().and(qOrgDeptPo.itIsRoot.isTrue()));
        }else {
            // 非智库的节点  ---只能管理当前部门下的人 哪怕是一个科室也只能管理科室下的
            Long parentId = searchParamsDto.getParentId();
            if (null == parentId) {
//                long pId = OrgAccountHelper.getDeptId();
//                if(pId == 0){
//                    //平台根节点
//                    predicate = ExpressionUtils.and(predicate, qOrgDeptPo.id.isNull());
//                }else{
                    predicate = ExpressionUtils.and(predicate, qOrgDeptPo.id.eq(OrgAccountHelper.getDeptId()));
//                }
            } else {
                predicate = ExpressionUtils.and(predicate, qOrgDeptPo.parentId.eq(parentId));
            }
        }

        // 排序
        Sort sort = Sort.by(new Sort.Order(Sort.Direction.ASC, "sortNum"));

        // 执行Iterable转换List
        return Lists.newArrayList(orgDeptRepository.findAll(predicate, sort).iterator());
    }

    @Override
    public Page<OrgDeptPo> readAllByPage(OrgDeptParamsDto searchParamsDto, PageParamsDTO pageParamsDto, SortParamsDTO sortParamsDto) {
        QOrgDeptPo qOrgDeptPo = QOrgDeptPo.orgDeptPo;

        // 开启谓语查询条件
        Predicate predicate = qOrgDeptPo.id.isNotNull().and(qOrgDeptPo.deleted.eq(false));

        Long parentId = searchParamsDto.getParentId();
        if (null == parentId) {
            predicate = ExpressionUtils.and(predicate, qOrgDeptPo.parentId.isNull());
        } else {
            predicate = ExpressionUtils.and(predicate, qOrgDeptPo.parentId.eq(parentId));
        }

        String title = searchParamsDto.getTitle();

        if (!StringUtils.isEmpty(title)) {
            predicate = ExpressionUtils.and(predicate, qOrgDeptPo.title.like("%" + title + "%"));
        }

        // 排序
        Sort sort = sortParamsDto.getSort();
        if (null == sort) {
            sort = Sort.by(new Sort.Order(Sort.Direction.DESC, "createdDate"));
        }

        // 执行返回
        Pageable pageable = pageParamsDto.getPageableWithSort(sort);

        // 执行Iterable转换List
        return orgDeptRepository.findAll(predicate, pageable);
    }

    @Override
    public void create(OrgDeptParamsDto dto) throws DeptTitleExistedException, DeptCodeExistedException {
        if (titleExisted(dto.getParentId(), dto.getId(), dto.getTitle())) {
            throw new DeptTitleExistedException("部门名称已存在!");
        }

        if (codeExisted(dto.getParentId(), dto.getId(), dto.getCode())) {
            throw new DeptCodeExistedException("部门编码已存在!");
        }

        OrgDeptPo orgDeptPo = orgDeptMapper.dto2po(dto);
        // 设置所属机构
//        if(dto.isItIsOrg()){
//            if(dto.getOrgId() != null){
//                OrgPo orgPo = orgRepository.findById(dto.getOrgId()).orElse(null);
//                if (null != orgPo) {
//                    orgDeptPo.setOrg(orgPo);
//                }
//            }
//        }else{
//            orgDeptPo.setOrg(null);
//        }
        orgDeptRepository.save(orgDeptPo);
    }

    @Override
    public void update(OrgDeptParamsDto dto) throws DeptTitleExistedException, DeptCodeExistedException {
        OrgDeptPo po = orgDeptRepository.findById(dto.getId()).orElse(null);
        if (null != po) {
            if (titleExisted(dto.getParentId(), dto.getId(), dto.getTitle())) {
                throw new DeptTitleExistedException("部门名称已存在!");
            }

            if (codeExisted(dto.getParentId(), dto.getId(), dto.getCode())) {
                throw new DeptCodeExistedException("部门编码已存在!");
            }

            orgDeptMapper.updatePoFromDto(dto, po);
            // 设置所属机构
//            if(dto.isItIsOrg()){
//                if(dto.getOrgId() != null){
//                    OrgPo orgPo = orgRepository.findById(dto.getOrgId()).orElse(null);
//                    if (null != orgPo) {
//                        po.setOrg(orgPo);
//                    }
//                }
//            }
            orgDeptRepository.save(po);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(OrgDeptParamsDto dto) {
        OrgDeptPo orgDeptPo = orgDeptRepository.findById(dto.getId()).orElse(null);
        if (null != orgDeptPo) {
            // 逻辑标记需删除部门
            orgDeptRepository.logicDelete(dto.getId());
            if(dto.getOrgId() != null && dto.isItIsOrg()){
                // 获取根节点
                Set<OrgDeptPo> depts;
                OrgDeptPo rootDept = null;
                OrgPo orgPo = orgRepository.findById(dto.getOrgId()).orElse(null);
                if (null != orgPo) {
                    depts = orgPo.getDepts();
                    for (OrgDeptPo dept : depts) {
                        if (dept.getOrg().getId().equals(orgDeptPo.getOrg().getId()) && dept.isItIsOrg()) {
                            rootDept = dept;
                        }
                    }
                    // 将该部门下的人员全部移至根节点
                    List<OrgUserPo> users = orgDeptPo.getUsers();
                    for (OrgUserPo user : users) {
                        // 删除原先的部门
                        user.getDepts().remove(orgDeptRepository.findById(dto.getId()).orElse(null));
                        // 增加根节点部门
                        user.getDepts().add(rootDept);
                        orgUserRepository.save(user);
                    }
                }
            }
        }
    }

    /**
     * 判断部门名称是否存在  父节点下
     *
     * @return 执行反馈
     */
    private boolean titleExisted(Long parentId, Long id, String title) {
        QOrgDeptPo qOrgDeptPo = QOrgDeptPo.orgDeptPo;
        Predicate predicate = qOrgDeptPo.id.isNotNull()
                .and(qOrgDeptPo.deleted.eq(false))
                .and(qOrgDeptPo.parentId.eq(parentId)
                .and(qOrgDeptPo.title.eq(title)));
        if(id != null){
            predicate = ExpressionUtils.and(predicate, qOrgDeptPo.id.ne(id));
        }
        return orgDeptRepository.exists(predicate);
    }

    /**
     * 判断部门编码是否存在
     *
     * @return 执行反馈
     */
    private boolean codeExisted(Long parentId, Long id, String code) {
        QOrgDeptPo qOrgDeptPo = QOrgDeptPo.orgDeptPo;
        Predicate predicate = qOrgDeptPo.id.isNotNull()
                .and(qOrgDeptPo.deleted.eq(false))
                .and(qOrgDeptPo.parentId.eq(parentId))
                .and(qOrgDeptPo.code.eq(code));
        if(id != null){
            predicate = ExpressionUtils.and(predicate, qOrgDeptPo.id.ne(id));
        }
        return orgDeptRepository.exists(predicate);
    }

    @Override
    public OrgDeptPo getByOrgId(Long id) {
        return orgDeptRepository.findOrgDeptPoByOrg_IdAndDeletedAndItIsRoot(id, false,true);
    }

    @Override
    public OrgDeptPo getOne(Long deptId) {
        return orgDeptRepository.findById(deptId).orElse(null);
    }

    @Override
    public OrgDeptPo getByOrgName(String orgName) {
        return orgDeptRepository.findOrgDeptPoByTitleAndDeletedIsFalse(orgName);
    }
}